import { BusinessStatus } from "~/src/enum"
import {GenTableColumnInitDto, GenTableInitDto, ProcessSql, PROCESS_SQL_CONSTANT, TableStructure } from "./sqlGen.domain"

/**
	sql 解析记录：
	1. 判断 CREATE TABLE  ，拆分 第一个 ( )  【 获取表名、表备注】
	2. 拆分 , 号
	3. 拆分 空格
	4. 获取 行数组 0,1 数据 , 并去除 引号 【 获取 列名、变量类型 】
	5. 遍历余下 行数组 判断关键字 [ NULL、COMMENT ]  【 获取是否必填、列备注】 (可判断 DEFAULT 关键字 获取 默认值)
	6. 匹配 PRIMARY KEY 关键字 获取 主键列。
*/

export class MysqlProcessSql implements ProcessSql {
	sqlVal:string
	constructor(sqlVal:string){
		this.sqlVal = sqlVal
	}
	sql2InitDto(): GenTableInitDto {
		return handleSql2Json(this.sqlVal)
	}

}

/**
 *  处理 sql 2 json
 * @param sqlVal  sql语句
 * @returns GenTableInitDto
 */
function handleSql2Json(sqlVal:string):GenTableInitDto{
	const sqlTrim = sqlVal.trim().toUpperCase()
	checkSqlLegal(sqlTrim)
	const tableStructure:TableStructure = disassemblyTableStructure(sqlTrim)
	const tableName = takeValWithoutWarp(tableStructure.tableName.trim())
	const tableColumns = buildSqlColumnDtos(tableStructure.tableColumns)

	return {
		name:tableName,columns:tableColumns,dbType:"MYSQL"
	}

}
/**
 * 检查建表sql是否合法
 * @param sqlStr sql字符串
 */
function checkSqlLegal(sqlStr:string){
	if(!sqlStr.startsWith(PROCESS_SQL_CONSTANT.CREATE_TABLE)){
		const msg = "请录入正确的建表语句，再尝试生成！"
		window.$message?.error(msg)
		throw new Error(msg)
	}
}
/**
 * 根据建表语句拆解表格结构对象
 * @param sqlVal  sql语句
 */
function disassemblyTableStructure(sqlVal:string):TableStructure{
	const begin:number = sqlVal.indexOf("(")
	const end:number = sqlVal.lastIndexOf(")")
	const tableName:string =  sqlVal.substring(0,begin).replace(PROCESS_SQL_CONSTANT.CREATE_TABLE,"").trim()
	const tableColumns:string[] = sqlVal.substring(begin+1,end).split(",")
	const tableTail:string =  sqlVal.substring(end+1)
	return {tableName,tableColumns,tableTail}
}
/**
 *  生成sql列对象
 * @param columns 列数组
 */
function buildSqlColumnDtos(columns:string[]):GenTableColumnInitDto[]{
	var idColumn:string = ""
	const result = columns.filter(it=>{
		// 过滤 声明行
		const val:string = it.trim()
		if(val.startsWith(PROCESS_SQL_CONSTANT.PRIMARY_KEY)){
			const primaryKey:string = val.replace(PROCESS_SQL_CONSTANT.PRIMARY_KEY,"")
		  idColumn = takeValWithoutWarp(primaryKey.trim(),"\\(`",2)
			return false;
		}
		return true;
	}).map(it=>{
		// 构建 列对象
		const columnDto:GenTableColumnInitDto = {name:"",type:"",isPk:BusinessStatus.No,isRequired:BusinessStatus.No}
		const val:string = it.trim()
		const blocks:string[] = val.split(PROCESS_SQL_CONSTANT.DEF_SKIP)
		columnDto.name = takeValWithoutWarp(blocks[0].trim())
		columnDto.type  = blocks[1]
		for(let i = 2 ; i<blocks.length-1 ; i++){
			const block:string = blocks[i]
			if(block == PROCESS_SQL_CONSTANT.NULL){
				columnDto.isRequired = blocks[i-1] == PROCESS_SQL_CONSTANT.NOT ? BusinessStatus.Yse : BusinessStatus.No
			}else if(block == PROCESS_SQL_CONSTANT.COMMENT && i+1 < blocks.length ){
				columnDto.comment = takeValWithoutWarp(blocks[++i])
			}
		}
		return columnDto;
	})
	if(idColumn){
		 result.forEach(it=>{
			if(it.name == idColumn){
				it.isPk = BusinessStatus.Yse
				return;
			}
		 })
	}
	return result
}
/**
 *  获取被包裹的值,并且转成小写
 * @param val  内容
 * @param warpVal  外包装的正则表达式
 * @param clearNum 外包装的数量
 */
function takeValWithoutWarp(val:string = "",warpVal:string = "[\`|\"|\']",clearNum:number = 1):string{
	const result = val.match("^"+warpVal)
	if(result){
		return val.substring(clearNum,val.length-clearNum)
	}
	return val
}

export { handleSql2Json }
